DATA      SEGMENT
;-接口区-
I8259_1   EQU   2B0H       ;8259的ICW1端口地址
I8259_2   EQU   2B1H       ;8259的ICW2端口地址
I8259_3   EQU   2B1H       ;8259的ICW3端口地址
I8259_4   EQU   2B1H       ;8259的ICW4端口地址
O8259_1   EQU   2B1H       ;8259的OCW1端口地址
O8259_2   EQU   2B0H       ;8259的OCW2端口地址
O8259_3   EQU   2B0H       ;8259的OCW3端口地址
;-提示信息区-
MES1      DB 'YOU CAN PLAY A KEY ON THE KEYBOARD!',0DH,0AH,24H
;-中断信息区-
MESS1     DB 'HELLO! THIS IS INTERRUPT    *  0  *!',0DH,0AH,'$'
MESS2     DB 'HELLO! THIS IS INTERRUPT    *  1  *!',0DH,0AH,'$'
MESS3     DB 'HELLO! THIS IS INTERRUPT    *  2  *!',0DH,0AH,'$'
MESS4     DB 'HELLO! THIS IS INTERRUPT    *  3  *!',0DH,0AH,'$'
MESS5     DB 'HELLO! THIS IS INTERRUPT    *  4  *!',0DH,0AH,'$'
MESS6     DB 'HELLO! THIS IS INTERRUPT    *  5  *!',0DH,0AH,'$'
MESS7     DB 'HELLO! THIS IS INTERRUPT    *  6  *!',0DH,0AH,'$'
MESS8     DB 'HELLO! THIS IS INTERRUPT    *  7  *!',0DH,0AH,'$'
DATA      ENDS

CODE      SEGMENT
          ASSUME CS:CODE,DS:DATA,ES:DATA
START:    
          ;数据段初始化
          MOV    AX,DATA
          MOV    DS,AX
          MOV    ES,AX
          ;向8259ICW1端口写13H 指定为片沿触发 
          MOV    DX,I8259_1          ;初始化8259的ICW1
          MOV    AL,13H              ;边沿触发、单片8259、需要ICW4
          OUT    DX,AL
         ;向8259ICW2端口写0B0H 设置中断号为0B0H
          MOV    DX,I8259_2          ;初始化8259的ICW4
          MOV    AL,0B0H             ;非自动结束EOI
          OUT    DX,AL
          ;向8259ICW4端口写03H 正常嵌套，非缓冲，自动结束,16位系统
          MOV    AL,03H
          OUT    DX,AL
          ;初始化8259的OCW1端口写00H 八个外部中断请求全部开放
          MOV    DX,O8259_1          
          MOV    AL,00H              ;打开IR0和IR1的屏蔽位
          OUT    DX,AL      

          ;16H是键盘中断
          ;1号功能读取普通键盘状态
          ;功能规定 若无字符输入 则零标志位置1
QUERY:    MOV    AH,1                ;判断是否有按键按下
          INT    16H
          JNZ    QUITM                ;有按键则退出
QUITM:    JMP QUIT
          ;向OCW3写入0CH 发起轮询命令
          MOV    DX,O8259_3          ;向8259的OCW3发送查询命令
          MOV    AL,0CH
          OUT    DX,AL
          ;将读出的查询字放入AL中
          IN     AL,DX               ;读出查询字
          MOV    AH,AL
          AND    AL,80H
          ;检测AL中的查询结果最高位是否为1 
          ;TEST指令执行AND X,Y操作，但并不将结果回传X，只修改标志位
          TEST   AL,80H              ;判断中断是否已响应 
          JZ     QUERY               ;最高位为0 没有响应则继续查询
          ;保留查询字的低3位
          MOV    AL,AH       
          AND    AL,07H
          ;根据低三位的值 判定是八个IR口中的哪一个发起的中断请求
          ;跳转到对应的中断处理程序
          CMP    AL,00H
          JE     IR0ISR              ;若为IR0请求，跳到IR0处理程序
          CMP    AL,01H
          JE     IR1ISR              ;若为IR1请求，跳到IR1处理程序
          CMP    AL,02H
          JE     IR2ISR               ;若为IR2请求，跳到IR1处理程序
          CMP    AL,03H     
          JE     IR3ISR               ;若为IR3请求，跳到IR1处理程序
          CMP    AL,04H
          JE     IR4ISR               ;若为IR4请求，跳到IR1处理程序
          CMP    AL,05H
          JE     IR5ISR             ;若为IR5请求，跳到IR1处理程序
          CMP    AL,06H
          JE     IR6ISR             ;若为IR6请求，跳到IR1处理程序
          CMP    AL,07H
          JE     IR7ISR             ;若为IR7请求，跳到IR1处理程序
          JMP    QUERY              ;无处理则回跳到QUERY处继续监听

;中断处理程序组 只对1段中断处理程序详细注释
;8个处理程序如出一辙
;0号中断处理程序
IR0ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS1     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;1号中断处理程序
IR1ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS2     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;2号中断处理程序
IR2ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS3     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;3号中断处理程序
IR3ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS4     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;4号中断处理程序
IR4ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS5     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;5号中断处理程序
IR5ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS6     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;6号中断处理程序
IR6ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS7     ;显示提示信息
          MOV    AH,09
          INT    21H
          JMP    EOI
;7号中断处理程序
IR7ISR:   MOV    AX,DATA
          MOV    DS,AX
          MOV    DX,OFFSET MESS8     ;显示提示信息
          MOV    AH,09
          INT    21H

          ;向8259通过OCW2端口发送中断结束命令EOI
EOI:      MOV    DX,O8259_2          ;向8259发送中断结束命令
          MOV    AL,20H
          OUT    DX,AL
          JMP    QUERY        ;继续监听按键或中断请求
          
          ;结束程序
QUIT:     MOV    AX,4C00H            ;结束程序退出
          INT    21H
CODE      ENDS
          END    START
